<?php
/*
|--------------------------------------------------------------------------
| Common function method
|--------------------------------------------------------------------------
*/

use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Database\Query\Builder as QueryBuilder;
use Hyperf\Database\Model\Builder as ModelBuilder;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Server\ServerFactory;
use Hyperf\Utils\ApplicationContext;
use Psr\Http\Message\ServerRequestInterface;
use Swoole\Websocket\Frame;
use Swoole\WebSocket\Server as WebSocketServer;
use Hyperf\Utils\Str;
use Hyperf\Redis\Redis;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;

/**
 * 容器实例
 *
 * @return ContainerInterface
 */
function di(): ContainerInterface
{
    return ApplicationContext::getContainer();
}

/**
 * Redis 客户端实例
 *
 * @return Redis|mixed
 */
function redis()
{
    return di()->get(Redis::class);
}

/**
 * Server 实例 基于 Swoole Server
 *
 * @return \Swoole\Coroutine\Server|\Swoole\Server
 */
function server()
{
    return di()->get(ServerFactory::class)->getServer()->getServer();
}

/**
 * WebSocket frame 实例
 *
 * @return mixed|Frame
 */
function frame()
{
    return di()->get(Frame::class);
}

/**
 * WebSocketServer 实例
 *
 * @return mixed|WebSocketServer
 */
function websocket()
{
    return di()->get(WebSocketServer::class);
}

/**
 * 缓存实例 简单的缓存
 *
 * @return mixed|\Psr\SimpleCache\CacheInterface
 */
function cache()
{
    return di()->get(Psr\SimpleCache\CacheInterface::class);
}

/**
 * Dispatch an event and call the listeners.
 *
 * @return mixed|\Psr\EventDispatcher\EventDispatcherInterface
 */
function event()
{
    return di()->get(Psr\EventDispatcher\EventDispatcherInterface::class);
}

/**
 * 控制台日志
 *
 * @return StdoutLoggerInterface|mixed
 */
function stdout_log()
{
    return di()->get(StdoutLoggerInterface::class);
}

/**
 * 文件日志
 *
 * @param string $name
 * @return LoggerInterface
 */
function logger(string $name = 'APP'): LoggerInterface
{
    return di()->get(LoggerFactory::class)->get($name);
}

/**
 * Http 请求实例
 *
 * @return mixed|ServerRequestInterface
 */
function request()
{
    return di()->get(ServerRequestInterface::class);
}

/**
 * 请求响应
 *
 * @return ResponseInterface|mixed
 */
function response()
{
    return di()->get(ResponseInterface::class);
}

/**
 * 获取邮件助手
 *
 * @return \App\Support\Mailer|mixed
 */
function email()
{
    return di()->get(App\Support\Mailer::class);
}

/**
 * 获取媒体文件url
 *
 * @param string $path 文件相对路径
 * @return string
 */
function get_media_url(string $path): string
{
    return sprintf('%s/%s', rtrim(config('domain.img_url'), '/'), ltrim($path, '/'));
}

/**
 * 随机生成图片名
 *
 * @param string $ext      图片后缀名
 * @param array  $filesize 图片文件大小信息
 * @return string
 */
function create_image_name(string $ext, array $filesize): string
{
    return uniqid() . Str::random() . '_' . $filesize[0] . 'x' . $filesize[1] . '.' . $ext;
}

/**
 * 判断0或正整数
 *
 * @param string|int $value  验证字符串
 * @param bool       $isZero 判断是否可为0
 * @return bool
 */
function check_int($value, $isZero = false): bool
{
    $reg = $isZero ? '/^[+]{0,1}(\d+)$/' : '/^[1-9]\d*$/';
    return is_numeric($value) && preg_match($reg, $value);
}

/**
 * 解析英文逗号',' 拼接的 ID 字符串
 *
 * @param string|int $ids 字符串(例如; "1,2,3,4,5,6")
 * @return array
 */
function parse_ids($ids): array
{
    return array_unique(explode(',', trim($ids)));
}

/**
 * 推送消息到 Redis 订阅中
 *
 * @param string       $chan
 * @param string|array $message
 */
function push_redis_subscribe(string $chan, $message)
{
    redis()->publish($chan, is_string($message) ? $message : json_encode($message));
}

/**
 * 生成随机文件名
 *
 * @param string $ext 文件后缀名
 * @return string
 */
function create_random_filename(string $ext): string
{
    $ext = $ext ? '.' . $ext : '';
    return Str::random(10) . uniqid() . $ext;
}

/**
 * 获取客户端你真实IP
 *
 * @return mixed|string
 */
function get_real_ip(): string
{
    if ($ip = request()->getHeaderLine('x-real-ip')) {
        return $ip;
    } else if ($ip = request()->getHeaderLine('x-forwarded-for')) {
        return $ip;
    }

    return request()->getServerParams()['remote_addr'] ?? '';
}


/**
 * 通过查询构造器读取分页数据
 *
 * @param QueryBuilder|ModelBuilder $model  查询构造器
 * @param array                     $fields 查询字段
 * @param int                       $page   当前分页
 * @param int                       $size   分页大小
 * @return array
 */
function toPaginate($model, array $fields = ['*'], int $page = 1, int $size = 15): array
{
    $total = $model->count();

    $data = [
        'rows'     => [],
        'paginate' => [
            'page'  => $page,
            'size'  => $size,
            'total' => $total,
        ]
    ];

    if ($total > 0) $data['rows'] = $model->forPage($page, $size)->get($fields)->toArray();

    if ($data['rows'] && $model instanceof QueryBuilder) {
        foreach ($data['rows'] as &$row) {
            $row = (array)$row;
        }
    }

    return $data;
}
function info($msg, $info = [])
{
    \Hyperf\Utils\ApplicationContext::getContainer()->get(\Hyperf\Logger\LoggerFactory::class)->get('app')->info($msg, $info);
}


// 时间相减2021-03-31 14:16:13
function timeDiff2($lt, $gt, $isMicro=false)
{
    info('timediff2', [$lt, $gt]);
    $tmplt = explode('.', $lt);
    $tmpgt = explode('.', $gt);

    $datelt = data_get($tmplt, '0', '');
    $dategt = data_get($tmpgt, '0', '');

    $microlt = data_get($tmplt, '1', '000');
    $microgt = data_get($tmpgt, '1', '000');

    if (empty($lt) || empty($gt)) {
        return "00:00:00";
    }

    $date1 = strtotime($datelt);

    $date2 = strtotime($dategt);

    $diff = abs($date2 - $date1);

    if ($microgt < $microlt) {
        $diff = $diff - 1;
        $microgt += 1000;
    }

    $micdiff = abs($microgt - $microlt);

    $hours = substr(str_pad(floor(($diff / (60 * 60))), 2, '0', STR_PAD_LEFT), -8);

    $minutes = substr(str_pad(floor(($diff - $hours * 60 * 60) / 60), 2, '0', STR_PAD_LEFT), -8);

    $seconds = substr(str_pad(floor(($diff - $hours * 60 * 60 - $minutes * 60)), 2, '0', STR_PAD_LEFT), -8);

    $return = "$hours:$minutes:$seconds";
    if ($micdiff > 0 || $isMicro) {
        if ($micdiff < 10) {
            $return .= ".00$micdiff";
            return $return;
        }
        if ($micdiff < 100) {
            $return .= ".0$micdiff";
            return $return;
        }
        $return .= ".$micdiff";
    }
    return $return ;
}

// 用时相减14:16:26
function timeDiff($datelt, $dategt)
{
//    info('timediff', [$dategt, $datelt]);
    if (empty($dategt) || empty($datelt)) {
        return "00:00:00";
    }
    $data_one = explode(':',$dategt);
    $data_two = explode(':',$datelt);
    $hour = bcsub((int)$data_one['0'],(int)$data_two['0'],0);
    $min = bcsub((int)$data_one['1'],(int)$data_two['1'],0);
    $sec = bcsub((int)$data_one['2'],(int)$data_two['2'],0);

    if ($sec<0) {
        $min = bcsub($min,1,0);
        $sec = bcadd($sec,60,0);
    }

    if ($min<0) {
        $hour = bcsub($hour,1,0);
        $min = bcadd($min,60,0);
    }

    if ($hour<10 && $hour>=0) {
        $hour='0'.$hour;
    }
    if ($min<10  && $hour>=0) {
        $min='0'.$min;
    }
    if ($sec<10  && $hour>=0) {
        $sec='0'.$sec;
    }

    return $hour.":".$min.":".$sec;
}

function time2Min($time)
{
    $return = '';
    try {
        $timeP = explode('.', $time);
        $timeArr = explode(':',data_get($timeP, 0, ''));

        $return = bcadd(bcadd($timeArr[0] * 60, $timeArr[2] / 60, 4), $timeArr[1], 4);
    } catch (\Exception $e) {}
    return $return;
}

function micSec2Time($micSec)
{
    $micSec = intval($micSec);
    $micdiff = substr($micSec, -3);

    $diff = substr($micSec, 0, -3);


//转换时间差的格式

//    $years = floor($diff / (365*60*60*24));
//
//    $months = floor(($diff - $years * 365*60*60*24)  / (30*60*60*24));
//
//    $days = floor(($diff - $years * 365*60*60*24 -  $months*30*60*60*24)/ (60*60*24));

    $hours = substr(str_pad(floor(($diff / (60 * 60))), 2, '0', STR_PAD_LEFT), -8);

    $minutes = substr(str_pad(floor(($diff - $hours * 60 * 60) / 60), 2, '0', STR_PAD_LEFT), -8);

    $seconds = substr(str_pad(floor(($diff - $hours * 60 * 60 - $minutes * 60)), 2, '0', STR_PAD_LEFT), -8);

    $return = "$hours:$minutes:$seconds";
    if ($micdiff > 0) {
        if ($micdiff < 10) {
            $return .= ".00$micdiff";
        }
        if ($micdiff < 100) {
            $return .= ".0$micdiff";
        }
        $return .= ".$micdiff";
    }
//    info('timediff2', [$lt, $gt, $return]);
    return $return ;
}

function time2Hour($time)
{
    $return = '';
    try {
        $timeArr = explode(':',$time);
        $return = bcadd(bcadd($timeArr[1] / 60, $timeArr[2] / 3600, 4), $timeArr[0], 4);
    } catch (\Exception $e) {}

    return $return;
}

function time2MicSec($time)
{
    $return = '';
    try {
        $timeP = explode('.', $time);
        $timeArr = explode(':',data_get($timeP, 0, ''));

        $return = bcadd(bcadd(bcadd($timeArr[0] * 60 * 60 * 1000, $timeArr[1] * 60 * 1000, 4), $timeArr[2] * 1000, 4), data_get($timeP, 1, ''), 4);
    } catch (\Exception $e) {}
    return $return;
}

function min2peisu($time)
{
    $return = '';
    if (empty($time)) {
        return "0'0\"";
    }
    try {
        $timeArr = explode('.',$time);
        $sec = round(bcsub($time, $timeArr[0], 4) * 60, 0);
        if ($sec < 10) {
            $sec = '0'.$sec;
        }
        $return = $timeArr[0] . "'" . $sec . "\"";
    } catch (\Exception $e) {}

    return $return;
}

function peisu2min($peisu)
{
    $preg = "/^([0-9]{1,3})'([0-9]{1,2})\"$/";
    if (preg_match($preg, $peisu, $arr)) {
        return bcadd(data_get($arr, 2, 0) / 60, data_get($arr, 1, 0), 4);
    }
}

function quzheng($chengji='')
{
    if (empty($chengji)) {
        return '';
    }
    $timeArr = explode('.',$chengji);
    if (empty(data_get($timeArr, '1', '')) || data_get($timeArr, '1', '') == '000') {
        return (data_get($timeArr, '0', ''));
    } else {
        return timeAdd(data_get($timeArr, '0', ''), '00:00:01');
    }

}

function timeAdd($time_one,$time_two){

    $tmplt = explode('.', $time_one);
    $tmpgt = explode('.', $time_two);

    $datelt = data_get($tmplt, '0', '');
    $dategt = data_get($tmpgt, '0', '');

    $microlt = data_get($tmplt, '1', '000');
    $microgt = data_get($tmpgt, '1', '000');

    $data_one = explode(':',$datelt);
    $data_two = explode(':',$dategt);


    $hour = bcadd((int)$data_one['0'],(int)$data_two['0'],0);
    $min = bcadd((int)$data_one['1'],(int)$data_two['1'],0);
    $sec = bcadd((int)$data_one['2'],(int)$data_two['2'],0);
    $mic = bcadd((int)$microlt,(int)$microgt,0);
    if ($mic >= 1000) {
        $sec = bcadd($sec, 1, 0);
        $mic = bcsub($mic, 1000, 0);
    }

    if ($sec>59) {
        $min = bcadd($min,1,0);
        $sec = bcsub($sec,60,0);
    }

    if ($min>59) {
        $hour = bcadd($hour,1,0);
        $min = bcsub($min,60,0);
    }

    if (abs($hour)<10) {
        if ($hour > 0) {
            $hour='0'.$hour;
        } else {
            $hour = sprintf("%02d", $hour);
        }
//        $hour = substr(str_pad($hour, 2, '0', STR_PAD_LEFT), -2);
//
    }
    if ($min<10) {
        $min='0'.$min;
    }
    if ($sec<10) {
        $sec='0'.$sec;
    }
    if ($mic < 100) {
        $mic = '0'.$mic;
    }
    if ($mic < 10) {
        $mic = '0'.$mic;
    }

    if ($mic == '000') {
        return $hour.":".$min.":".$sec;
    }
    return $hour.":".$min.":".$sec.".".$mic;
}

function toBaiduLocation($lng,$lat){
    $ak = 'EBzLOLZMqAuxB0PLa16Wu9aX2363jZVX';
    $url = 'https://api.map.baidu.com/geoconv/v1/?coords='.$lng.','.$lat.'&from=1&to=5&ak='.$ak;
    $result =  get($url)->getBody()->getContents();
    $json = json_decode($result,true);
    if($json['status'] == 0 && isset($json['result'][0])){
        $res = $json['result'][0];
        return ['lng'=>$res['x'],'lat'=>$res['y']];
    }
    return ['lng'=>$lng,'lat'=>$lat];
}


function isDateTime($time){
    $preg = '/^([12]\d\d\d)-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[0-1]) ([0-1]\d|2[0-4]):([0-5]\d)(:[0-5]\d)?$/';

    return preg_match($preg,$time);
}

function getAgeByBirth($birth)
{
    if (empty($birth)) {
        return -1;
    }
    $age = strtotime($birth);
    list($y1,$m1,$d1) = explode("-", date('Y-m-d', $age));
    $now = strtotime('now');
    list($y2,$m2,$d2) = explode("-", date('Y-m-d', $now));
    $age = $y2-$y1;
    if ((int)($m2.$d2) < (int)($m1.$d1)) {
        $age -= 1;
    }
    return $age;
}

function arraySort($array, $keys, $sort = SORT_ASC) {
    $keysValue = [];
    foreach ($array as $k => $v) {
        $keysValue[$k] = $v[$keys];
    }
    array_multisort($keysValue, $sort, $array);
    return $array;
}
function get_millisecond()
{
    $time = explode(" ", microtime());
    $time = $time [1] . ($time [0] * 1000);
    $time2 = explode(".", $time);
    $time = $time2 [0];
    $time = substr(str_pad($time, 13, '0', STR_PAD_RIGHT), -13);
    return $time;
}

function minpeisu2shisu($minpeisu)
{
    if (!$minpeisu) {
        return 0;
    }
    return round(60 / $minpeisu, 2);
}

function toGaodeLocation($lng,$lat, $from='gps'){
    $ak = 'b8285b9a31f1dda65d6a6b4f2ed30bf1';
    $url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=$lng,$lat&coordsys=$from&output=json&key=$ak";
//    $url = "https://restapi.amap.com/v3/assistant/coordinate/convert?parameters?locations=$lng,$lat&coordsys=gps&key=$ak";
    $client = new \GuzzleHttp\Client();
    $result =  $client->get($url)->getBody()->getContents();
    $json = json_decode($result,true);
    if($json['status'] == 1 ){
        $res = data_get($json, 'locations', '');
        $exp = explode(',', $res);
        return ['lng'=>$exp['0'],'lat'=>$exp['1']];
    }
    return ['lng'=>$lng,'lat'=>$lat];
}
function array_sort2($arr,$keys,$orderby='asc'){

    $keysvalue = $new_array = array();

    foreach ($arr as $k=>$v){

        $keysvalue[$k] = data_get($arr, $keys, '');

    }

    if($orderby== 'asc'){

        asort($keysvalue);

    }else{

        arsort($keysvalue);

    }

    reset($keysvalue);

    foreach ($keysvalue as $k=>$v){

        $new_array[] = $arr[$k];

    }

    return $new_array;

}

function obj_to_arr($obj)
{
    return json_decode(json_encode($obj), true);
}

function array_like($array, $search, $limit = 10)
{
    $count = 0;
    $result = [];
    foreach ($array as $v) {
        if (strstr($v, $search) !== false) {
            array_push($result, $v);
            $count++;
            if ($count >= $limit) {
                break;
            }
        }
    }

    return $result;
}


function array_pull_cloum($arr, $keys)
{
    $r = [];
    foreach ($arr as $k => $v) {
        foreach ($v as $k2 => $v2) {
            if (in_array($k2, $keys)) {
                $r[$k][$k2] = data_get($v, $k2);
            }
        }

    }

    return $r;
}

function time2hz($time)
{
    $r = explode(':', $time);
    $str = intval(data_get($r, '0', '0')).'小时'.intval(data_get($r, '1', 0)).'分钟'.intval(data_get($r, '2', '0')).'秒';
    return $str;
}